﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.IO;
using System.Diagnostics;
using System.Globalization;
using System.Text.RegularExpressions;
//using Agos.Utils;
using Logging;

namespace ENICHIUSURA.Utils
{
    class FileUtils
    {
        public static bool SearchInDirectory(string path, string keyword)
        {
            bool found = false;

            return found;
        }

        public static void CopyRenamed(String oldFilename, String newFilename)
        {
            FileInfo file = new FileInfo(oldFilename);
            FileInfo newFile = new FileInfo(newFilename);

            if (file.Extension == ".pdf" || file.Extension == ".jpg")
            {
                if (!newFile.Exists)
                {
                    System.IO.FileInfo filee = new System.IO.FileInfo(newFilename);
                    filee.Directory.Create(); //nothing will happen if the directory exists
                }
                //try catch unauthorized exception
                File.Copy(oldFilename, newFilename,true); //copies oldFilename to newFilename(path to newFilename must be prior created)
            }  
        }

        public static List<FileInfo> files = new List<FileInfo>();  // List that will hold the files and subfiles in path
        public static List<DirectoryInfo> folders = new List<DirectoryInfo>(); // List that hold direcotries that cannot be accessed
        public static void FullDirList(DirectoryInfo dir, string searchPattern)
        {
            // Console.WriteLine("Directory {0}", dir.FullName);
            // list the files
            try
            {
                foreach (FileInfo f in dir.GetFiles(searchPattern, SearchOption.AllDirectories))
                {
                    //Console.WriteLine("File {0}", f.FullName);
                    files.Add(f);
                }
            }
            catch
            {
                Console.WriteLine("Directory {0}  \n could not be accessed!!!!", dir.FullName);
                return;  // We alredy got an error trying to access dir so dont try to access it again
            }

            // process each directory
            // If I have been able to see the files in the directory I should also be able 
            // to look at its directories so I dont think I should place this in a try catch block


        }

        public static string TwoLevelTraverse(string extractedDate, string codClient,DirectoryInfo rootDir)
        {
            string[] potentialPath = new string[2];
            foreach (string firstLevel in Directory.GetDirectories(rootDir.FullName))
                foreach (string secondLevel in Directory.GetDirectories(firstLevel))
                {
                    if ((potentialPath[0] = PrepareFilePath(extractedDate, codClient, secondLevel)[0]) != "")
                    {
                        // not all path are written in the same case
                        potentialPath[1] = codClient;
                        if (Directory.Exists(potentialPath[0])) // Directory.Exists is case insensitive 
                        {
                            //verifica fisierele din data
                            //DirectoryInfo allFiles = new DirectoryInfo(potentialPath[0]);
                            foreach(string finalLevel in Directory.GetDirectories(potentialPath[0]))
                            
                            if (Regex.Replace(finalLevel, "[^0-9]", "").Trim() == codClient)//remove letters
                                return potentialPath[0] += potentialPath[1];
                        }
                    }
                }
            return "";
        }

        public static string[] PrepareFilePath(string extractedDate, string codClient, string initialPath)
        {
            string[] searchPath = new string[2]{"",""};
            DateTime date = DateTime.MinValue;
            if (extractedDate != "" && codClient != "")
            {
                date = DateTime.Parse(extractedDate);
                searchPath = new string[2] ;
                string month = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(date.Month).ToUpper();
                string day = date.Day.ToString();
                string year = date.Year.ToString();
                string folderDate = date.ToString("dd'.'MM'.'yyyy ");
                searchPath[0] += initialPath += @"\" + year + @"\" + month + " " + year + @"\" + folderDate + @"\";
                searchPath[1] += codClient + @"\";
                return searchPath;
            }
            return searchPath;
        }

        /// <summary>
        /// Wrapper for calling GetFiles() which will search for files in all the subdirectories
        /// </summary>
        /// <param name="rootDirectory"></param>
        /// <returns></returns>
        public static IEnumerable<System.IO.FileInfo> BuildFileList(DirectoryInfo rootDirectory)
        {
            IEnumerable<System.IO.FileInfo> fileList = null;
            Debug.WriteLine("Scanning second path for files.Entered at " + DateTime.Now.TimeOfDay);
            try
            {
                fileList = rootDirectory.GetFiles("*.*", System.IO.SearchOption.AllDirectories); //only pdf,jpg ?
            }
            catch (Exception e)
            {
                Logger.LogInfo("Exception at GetFiles"+e.ToString());
            }
            Debug.WriteLine("Finished scanning" + DateTime.Now.TimeOfDay);
            return fileList;
        }

        public static Dictionary<int, List<FileInfo>> BuildDictionaryFromFilesList(IEnumerable<FileInfo> fileList)
        {
            Dictionary<int, List<FileInfo>> filesDict = new Dictionary<int,List<FileInfo>>();
            
            int key = 0;
            
                for (int i = 0; i < fileList.Count(); i += 1)
                {
                    FileInfo currentFile = fileList.ElementAt(i);
                    if ((currentFile.Extension == ".pdf" || currentFile.Extension == ".jpg"))
                    {
                        key = ParseParentDirectory(currentFile); //the directory name serves as key == cod_vel

                        if (key != 0)
                        {
                            if (!filesDict.ContainsKey(key))
                            {
                                filesDict.Add(key, new List<FileInfo> { currentFile });
                            }
                            else //already exists the key add to its collection
                            {
                                List<FileInfo> currentColl = filesDict[key];
                                currentColl.Add(currentFile);
                                filesDict[key] = currentColl;
                            }
                        }
                    }
                }
                return filesDict;
        }

        //the parent directory name of the file is cod_vel
        public static int ParseParentDirectory(FileInfo file)
        {
            int key = 0;
            string parentDirectoryName;
            try
            {
                parentDirectoryName = file.Directory.Name; //Path to long exception ..
            }
            catch (PathTooLongException pe)
            {
                Logger.LogInfo(pe.ToString());
                return key;
            }
            catch (Exception exc)
            {
                Logger.LogInfo("Exception at ParseParentDir:" + exc.ToString());
                return key;
            }

            if (parentDirectoryName != null)
                parentDirectoryName = new string( parentDirectoryName.Where(c => (char.IsDigit(c) 
                          )).ToArray());

                try
                {
                    if (parentDirectoryName != "")
                    {
                        key = Int32.Parse(parentDirectoryName);
                    }
                }
                catch (OverflowException e)
                {
                    Logger.LogInfo(e.Message); //valore trop grande
                    return key;
                }
                catch (Exception e)
                {
                    Logger.LogInfo(e.ToString());
                    return key;
                }

            return key;
        }
        /// <summary>
        /// Remove non-digits 
        /// </summary>
        /// <param name="theString"></param>
        /// <returns></returns>
        public static int ParseCodVel(string theString)
        {
            int key = 0;

            if (theString != "" && theString != null)
            {
                char[] arr = theString.Where(c => (char.IsDigit(c)
                              )).ToArray();

                theString = new string(arr); //removed all characters and whitespaces

                try
                {
                    key = Int32.Parse(theString);
                }
                catch (Exception e)
                {
                    Logger.LogInfo(e.ToString());
                    return key;
                }
            }

            return key;
        }

        public static string AppendDateToFileName(string fileName)
        {
            string name = fileName.Remove(fileName.LastIndexOf("."));
            string extension = fileName.Substring(fileName.LastIndexOf(".")); //.xls

            DateTime date = DateTime.Now;
            CultureInfo english = new CultureInfo("en-US");
            string month = english.DateTimeFormat.GetMonthName(date.Month).ToUpper();
            month = FileUtils.enCultureToItalian(month);
            string day = date.Day.ToString();
            string year = date.Year.ToString();

            return name + "_" + month + "_" + day + "_" + year + extension;
        }

        public static string enCultureToItalian(string monthName)
        {
            Dictionary<string, string> monthsAssociation = new Dictionary<string, string>
            {
               {"JANUARY","gennaio"},
               {"FEBRUARY","febbraio"},
               {"MARCH","marzo"},
               {"APRIL","aprile"},
               {"MAY","maggio"},
               {"JUNE","giugno"},
               {"JULY","luglio"},
               {"AUGUST","agosto"},
               {"SEPTEMBER","settembre"},
               {"OCTOBER","ottobre"},
               {"NOVEMBER","novembre"},
               {"DECEMBER","dicembre"}
            };
            return monthsAssociation[monthName];
        }

        public static FileStream OpenFile(string path)
        {
            FileStream fs = null;
            if (!File.Exists(path))
            {
                try
                {
                    fs = File.Open(path, FileMode.Create);
                }
                catch (DirectoryNotFoundException e)
                {
                    FileInfo fi = new FileInfo(path);
                    fi.Directory.Create();
                    fs = File.Open(path, FileMode.CreateNew);
                }
            }
            else
            {
                fs = File.Open(path,FileMode.Open);
            }
            return fs;
        }
    
        /// <summary>
        /// If we try to acces a FileInfo object, FilePathTooLong exception will be generated if fN >260
        /// This exception is not generated when indexing ( by .GetFiles method) :|
        /// </summary>
        /// <param name="fileInfos">Collection of files</param>
        /// <returns></returns>
        public static IEnumerable<FileInfo>  RemovePtlE(IEnumerable<FileInfo> fileInfos) 
        {
            List<FileInfo> buffer = new List<FileInfo>(fileInfos);
            string current = null;
            int pathsTooLong = 0;
            for (int i = 0; i < buffer.Count; i ++)
            {
                try
                {
                    current = buffer.ElementAt(i).FullName.ToString();
                }
                catch (PathTooLongException pl)
                {
                    buffer.RemoveAt(i);
                    i--;
                    pathsTooLong += 1;
                    Logger.LogInfo("PathTooLongException item:" + i);
                }
                catch (Exception exp)
                {
                    Logger.LogInfo("Exception pl item:" + i);
                }
            }

            return (IEnumerable<FileInfo>)buffer;
        }
    }
}
